package com.sky.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.UserConstant;
import com.sky.context.BaseContext;
import com.sky.dto.CategoryDTO;
import com.sky.dto.CategoryPageQueryDTO;
import com.sky.entity.Category;
import com.sky.exception.ParamErrorException;
import com.sky.mapper.CategoryMapper;
import com.sky.mapper.DishMapper;
import com.sky.mapper.SetMealMapper;
import com.sky.result.PageResult;
import com.sky.service.CategoryService;
import com.sky.utils.PageUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

@Service
@Slf4j
public class CategoryServiceImpl implements CategoryService {

    @Resource
    private CategoryMapper categoryMapper;

    @Resource
    private DishMapper dishMapper;

    @Resource
    private SetMealMapper setMealMapper;

    /**
     * 分页条件查询
     *
     * @param pageQuery
     * @return
     */
    @Override
    public PageResult pageQuery(CategoryPageQueryDTO pageQuery) {
        int page = pageQuery.getPage();
        int pageSize = pageQuery.getPageSize();
        PageUtils.validatePageParams(page, pageSize);

        // 开启分页
        PageHelper.startPage(page, pageSize);

        // 查询数据库
        Category category = new Category()
                .builder()
                .type(pageQuery.getType())
                .name(pageQuery.getName()).build();
        Page<Category> categoryList = categoryMapper.getCategoryList(category);
        return new PageResult(categoryList.getTotal(), categoryList.getResult());
    }

    /**
     * 添加分类
     *
     * @param categoryDTO
     */
    @Override
    public void addCategory(CategoryDTO categoryDTO) {
        // 合法性校验
        checkCategoryParams(categoryDTO);
        checkNameUnique(categoryDTO.getName());

        // 构建菜单数据
        Integer type = categoryDTO.getType();
        String name = categoryDTO.getName();
        Integer sort = categoryDTO.getSort();
        Category category = new Category().builder()
                .type(type).name(name).sort(sort).build();

        // 设置默认状态
        category.setStatus(UserConstant.STATUS_DISABLE);
        log.info("添加分类: {}", category);
        categoryMapper.save(category);
    }

    /**
     * 更新分类状态
     *
     * @param status     状态参数
     * @param categoryId 需要更新的分类id
     */
    @Override
    public void updateStatus(Integer status, Long categoryId) {
        // 参数校验
        if (!UserConstant.validateStatusLegal(status)) {
            throw new ParamErrorException("状态参数不合法");
        }
        checkCategoryById(categoryId);

        Category category = new Category().builder().id(categoryId).status(status).build();
        categoryMapper.update(category);
    }

    /**
     * 更新分类信息
     *
     * @param categoryDTO
     */
    @Override
    public void updateCategory(CategoryDTO categoryDTO) {
        // 参数校验
        checkCategoryParams(categoryDTO);
        checkCategoryById(categoryDTO.getId());

        // 属性拷贝
        Category category = new Category();
        BeanUtils.copyProperties(categoryDTO, category);

        // 参数设置
        category.setUpdateTime(LocalDateTime.now());
        category.setUpdateUser(BaseContext.getCurrentId());

        categoryMapper.update(category);
    }

    /**
     * 删除分类
     *
     * @param id
     */
    @Override
    public void deleteCategory(Long id) {
        checkCategoryById(id);

        // 校验分类是否被使用
        checkCategoryBeUsed(id);

        categoryMapper.deleteById(id);
    }

    /**
     * 根据分类的[类型]查询分类
     *
     * @param type 类型
     * @return
     */
    @Override
    public List<Category> getCategoryListByType(Integer type) {
        if (!UserConstant.validateTypeLegal(type)) {
            throw new ParamErrorException("分类类型不合法");
        }

        return categoryMapper.getCategoryList(new Category().builder().type(type).build());
    }

    /**
     * 校验分类id是否在其他实体中被使用
     * @param categoryId
     */
    private void checkCategoryBeUsed(Long categoryId) {
        if (!dishMapper.getByCategoryId(categoryId).isEmpty()) {
            throw new ParamErrorException("该分类已被菜品使用，无法删除");
        }
        if (!setMealMapper.getByCategoryId(categoryId).isEmpty()) {
            throw new ParamErrorException("该分类已被套餐使用，无法删除");
        }
    }

    /**
     * 校验参数的合法性
     * 1.分类名称不能为空
     * 2.分类类型不能为空，且必须符合系统要求
     * 3.分类排序不能为空
     * @param categoryDTO
     */
    private void checkCategoryParams(CategoryDTO categoryDTO) {
        if (categoryDTO.getName() == null || categoryDTO.getName().isEmpty()) {
            throw new ParamErrorException("分类名称不能为空");
        }
        if (categoryDTO.getType() == null || !UserConstant.validateTypeLegal(categoryDTO.getType())) {
            throw new ParamErrorException("分类类型错误");
        }

        if (categoryDTO.getSort() == null) {
            throw new ParamErrorException("分类排序不能为空");
        }
    }

    /**
     * 校验分类名称是否唯一
     * @param name
     */
    private void checkNameUnique(String name) {
        Category category = categoryMapper.getCategoryByName(name);
        if (Objects.nonNull(category)) {
            throw new ParamErrorException("菜品名称已存在");
        }
    }

    /**
     * 根据id校验分类是否存在
     * @param id
     */
    private void checkCategoryById(Long id){
        Category category = categoryMapper.getCategoryById(id);
        if (Objects.isNull(category)) {
            throw new ParamErrorException("分类不存在");
        }
    }
}
